本博客所有案例的开发环境为 VS2013 + SQL Server 2012
Entity Framework实体框架简介
Entity Framework 实体框架(EF)是ADO.NET的开源对象关系映射(ORM)框架,它是 .NET Framework 的一部分,是一组支持开发面向数据的软件应用程序的技术。微软为实现 .NET 跨平台,将 EF 从 .NET 分离,使EF更加组件化。2016年6月27日,Entity Framework 7作为实体框架核心 1.0 发布,与 ASP.Net Core 1.0 和 .Net Core 1.0 一起发布,重命名为凸显出它是完全重新而不是增量升级,同时,EF7并不会取代EF6。
在EF中的实体数据模型(EDM)由以下三种模型和具有相应文件扩展名的映射文件进行定义。
概念架构定义语言文件(.csdl)——定义概念模型
存储架构定义语言文件(.ssdl)——定义存储模型
映射规范语言文件(.msl)——定义存储模型与概念模型之间的映射M。
实体框架 使用这些基于XML的模型和映射文件将对概念模型中的实体和关系的创建、读取、更新、和删除操作转换为数据源中的等效操作。EDM 甚至支持将概念模型中的实体映射到数据源中的存储过程。
ORM(Object Relational Mapping)框架采用元数据来描述对象一关系映射细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。
广义上来说,ORM 可以被认为是 面向对象模型和关系型数据库的数据结构之间的相互转换。
狭义上来说,ORM 可以被认为是,基于关系型数据库的数据存储,实现了一个虚拟的面向对象的数据访问接口。理想情况下,基于这样一个面对对象的接口,持续化一个OO对象应该不需要了解任何关系型数据库存储数据的实现细节。
其他.NET ORM框架:
- PetaPoco : 与完备的 ORM 框架不同,PetaPoco 更加注重易用性和性能。使用 PataPoco 只需要引入一个C#文件,可以使用强类型的 POCO(Plain Old CLR Object),并支持 T4 模板生成的类等。此外,由于 PetaPoco 是开源项目,因此添加条件来处理如空间数据等特定情况会很容易。
- Dapper :
性能方面高于 PetaPoco,速度只稍逊于手工编码的数据访问层(DAL、Data AccessLayer),还有一些对初学者会有帮助的、位于官网上的系列博文和一些独立博文教程。
一、DataFirst
使用EF,创建Model (DataFirst)
在解决方案中,创建所使用的项目。例如:ASP网站项目、WinForm窗体项目……
在新建的项目中,添加 > 新建项 > 数据 > ADO.NET实体数据模型(.edmx)
在新建的.edmx中选择:从数据库生成(DatabaseFirst)
选择新建连接,填写连接数据库 > 填写登录数据库信息 > 选择或输入需要生成模型的数据库名称.
选择需要创建模型的表、视图、存储过程
点击下一步,直接生成(有些电脑可能会出现警告信息,忽视即可)。
(图片不清晰的话请在:浏览器上,鼠标右键,在新标签页中打开图片。即可看到清晰图片)
使用EF创建的内容
创建完成后,项目会默认引入两个命名空间:EntityFramework、System.Data.Entity
最外层为.edmx文件,EF模型设计器,展示从数据库创建的模型,包括:表名、属性(表字段)、导航属性(外键、表与表之间的对应关系)、表与表之间1对1、1对多的关系。
Model1.Context.tt
、Model.Designer.cs
、Model.edmx.diagram
、Model1.tt
Model1.Context.tt
:包含Model1.Context.cs
。Model1.Context.tt
由T4模板生成,不可更改,Model1.Context.cs
继承自DbContext
,包括构造方法(继承自父类的构造方法,并在此传递配置文件的数据库连接字符串)、各个表所对应的Dbset<T>
类型的自动属性。Model.Designer.cs
:自动生成,无需更改Model.edmx.diagram
:描述edmx文件的元素信息(名称、位置……)Model1.tt
:包含生成的Model.cs,自身由T4模板生成,无需修改
使用EF进行增删改查
查询
1 | StudentMISEntities stu = new StudentMISEntities(); |
增加
1 | Users userInfo = new Users(); |
修改
1 | StudentMISEntities stu = new StudentMISEntities(); |
删除
1 | StudentMISEntities stu = new StudentMISEntities(); |
二、ModelFirst
除了支持 DatabaseFirst 外,EF 还支持 ModelFirst 、 CodeFirst,这两种类型不同于DatabaseFirst 先建立好数据库而后映射 Model , ModelFirst 是通过 Model 映射创建数据库,而 CodeFirst 类似于 ModelFirst, 通过代码逻辑自行创建 Model 并映射数据库,但是不同于 ModelFirst 由 VS 自动创建。
Model先行,通过Model创建数据库
步骤:
在新建的项目中,添加 > 新建项 > 数据 > ADO.NET实体数据模型(.edmx)
在新建的.edmx中选择:空模型(ModelFirst)
在.edmx图形化窗口中,右键 > 新增 > 实体
在新增实体页面 填写: 实体名(表名)、是否创建键属性(是否创建主键)、属性名称、属性类型 > 确定
在.edmx图形化窗口中,在 实体 上右键 > 新增 > 标量属性(表字段)
选中标量属性,按快捷键 F4 或调出属性面板,可以更改标量属性的:类型、名称、长度(必改)
在多个实体,且实体之间有关联的时候,在.edmx图形化设计页面中,右键 > 新建 > 关联
在添加关联页面设置内容(默认即可)
在所有模型创建完毕,在.edmx页面 右键 > 根据模型生成数据库
在 “生成数据库 向导” 页面,新建数据库连接 > 设置连接字符串 > 选择需要创建表的数据库 > 点击下一步
生成数据库向导中,会生成 DDL(数据库设计语言),并另存为 .sql 文件
生成 .sql 文件后,建立的Model并没有映射到数据库引擎中,需要在 .sql 文件中,右键 > 执行,即可。
(图片不清晰的话请在:浏览器上,鼠标右键,在新标签页中打开图片。即可看到清晰图片)
注意事项:
- 新建 标量属性 后,需要在属性面板对 标量属性的 长度 和 数据类型 进行限制,string 长度即为数据库内字段的 NVarChar 的长度 。
- 在 .edmx 图形化页面 新建完实体 后,解决方案里面可能没有生成 Model.tt 文件(包含 Model 模型.cs),这时候在 .edmx 图形化页面: 右键 > 添加代码生成项 > 数据 >EF 版本.x DbContext 生成器 > 确定
- 关于实体更新
- 需映射数据库更新
- 更新实体后,VS 在生成的DDL数据库脚本中,是把原先创建好的表全部删除,再重新创建更新后的实体所对应的表,如果原数据表中存在数据,数据也会一并删除。(2). 在更新数据库时一定要谨慎,做好数据库备份,同时如果只是小的改动(扩大字符长度),手动在数据库里 修改即可,或者仅把更新的sql脚本部分拷贝出来,复制到SQL Server执行
- 需映射数据库更新
三、CodeFirst
先写代码,通过代码创建实体,映射数据库
步骤:
新建项目,在项目里面通过 NuGet程序包 安装EntityFramework(该操作会自动引入EntityFramework以及相对应的命名空间)
在配置文件里面添加连接字符串
1
2
3<connectionStrings>
<add name="CodeFirstDemo" connectionString="server=.;uid=用户;pwd=密码;database=Test2" providerName="System.Data.SqlClient"/>
</connectionStrings>创建类 .cs ,设置类的属性、类之间的关联
studentInfo
1 | using System; |
classInfo
1 | using System; |
- 创建 EF数据操作类 codeFirstDbcontex
1 | using System; |
- 执行
1 | codeFirstDbcontext db = new codeFirstDbcontext(); |
(图片不清晰的话请在:浏览器上,鼠标右键,在新标签页中打开图片。即可看到清晰图片)
四、Linq查询和Lambda查询
Linq查询
Linq查询全部列并降序
1 | var userInfoList = from u in db.Users |
Linq分页
1 | int pageIndex = 3; |
Linq查询部分列
1 | var userInfoList = from u in db.Users |
Lambda查询
过滤筛选
1 | var userInfoList = db.Users.Where<Users>(u => u.id > 8); |
Lambda升序排序排序查询
对Id进行升序排序排序
1 | var userInfoList = db.Users.Where<Users>(U => true).OrderBy<Users, int>(u => u.id); |
对Id进行降序排序排序
1 | var userInfoList = db.Users.Where<Users>(U => true).OrderByDescending<Users, int>(u => u.id); |
在以用户名为前提倒序排序的基础上,如果用户名相同,则使用Id作为依据对用户名相同的用户进行倒序排序
1 | var userInfoList = db.Users.Where<Users>(u => true).OrderByDescending(u => u.uName).ThenByDescending<Users,int>(u => u.id); |
Lambda分页查询
1 | int pageIndex = 3; |